﻿using System;
using System.ComponentModel.DataAnnotations;
using System.Reflection;

namespace SimJsonRpc
{
    public class RpcMethodInfo
    {
        public Type serviceType { get; set; }
        public MethodInfo Method { get; }
        public object[] ConvertedParameters { get; }
        public object[] RawParameters { get; }

        public RpcMethodInfo(MethodInfo method, object[] convertedParameters, object[] rawParameters)
        {
            this.Method = method;
            this.ConvertedParameters = convertedParameters;
            this.serviceType = method.DeclaringType;
        }

        public bool IsParametersValid()
        {
            var parameterInfoList = this.Method.GetParameters();
            for (int i = 0; i < Math.Min(parameterInfoList.Length, this.ConvertedParameters.Length); i++)
            {
                var validations = parameterInfoList[i].GetCustomAttributes(typeof(ValidationAttribute), true);
                foreach (ValidationAttribute validationAttribute in validations)
                {
                    var paramValue = this.ConvertedParameters[i];
                    var parameterType = parameterInfoList[i].ParameterType;
                    if (!validationAttribute.IsValid(paramValue))
                    {
                        throw new ArgumentException(validationAttribute.FormatErrorMessage(parameterInfoList[i].Name));
                    }
                }
                var properties = parameterInfoList[i].ParameterType.GetProperties(BindingFlags.Instance | BindingFlags.Public);
                foreach (var property in properties)
                {
                    var propertyValidations = property.GetCustomAttributes(typeof(ValidationAttribute), true);
                    foreach (ValidationAttribute validationAttribute in propertyValidations)
                    {
                        var v = property.GetValue(this.ConvertedParameters[i]);
                        if (!validationAttribute.IsValid(v))
                        {
                            throw new ArgumentException(validationAttribute.FormatErrorMessage(parameterInfoList[i].Name + " " + property.Name));
                        }
                    }
                }

            }
            return true;
        }
    }
}
